home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
clipper
/
regxsrch.zip
/
REGXSRCH.C
< prev
Wrap
C/C++ Source or Header
|
1992-01-27
|
7KB
|
202 lines
/*
* regxsrch.c Tue Jan 21 1992 15:28:47
*
*
* Synopsis:
* ~~~~~~~~~
* A regular-expression searcher for Clipper. Uses the GNU regex library
* (as contained in the GNUISH MSDOS project's GNULIB, available in the
* pd:<msdos.gnuish> directory on Simtel20 and the mirror sites) to do
* the actual regex searching; thus the Clipper program must be linked
* against the GNU library (large model version) as well as this code and
* the C library.
*
* Note that this makes no re_set_syntax() call, so the regex functions
* are left to use the regex library's compile-time default syntax code.
* As the regex library is distributed, this is 0, giving the egrep syntax
* except that `\|' is required for the OR operator (`|' by itself is just
* a literal), and `\(' and `\)' are required for grouping (`(' and `)' are
* literals). See the file regex.h in the GNULIB or regexlib distributions
* for details of the available options.
*
*
* Warning:
* ~~~~~~~~
* I consider this release a Beta test version. There are no known bugs,
* and I have tested it thoroughly, but I will not accept responsibility
* for anything untoward it may do. If it sinks your house in a swamp,
* kills your dog, and phones your boss and calls him a dirty bastard,
* you will have only yourself to blame. However, I would appreciate
* hearing of any bugs you may find, and I will probably fix them.
*
*
* Notes:
* ~~~~~~
* This code #includes a header clipper.h, which is simply the virtual
* concatenation of the files nandef.h and extend.h distributed with Clipper.
*
* In case of difficulty using this together with other libraries (such as
* with super.lib), use the linker option /NODEFAULTLIBRARYSEARCH (/NOD)
* and specify the C library llibca.lib (*not* llibce.lib) explicitly.
*
* To compile this, use MS C switches '-AL -Zl -Oalt -FPa -Gs'. For example,
* if your default rule for C in make.ini uses $(MODEL),
*
* make regxsrch.obj MODEL=L CFLAGS='-Zl -Oalt -FPa -Gs'
*
* Assuming you are using GNU make and have the following default rule in
* make.ini:
*
* # To produce a `.exe' file from a `.prg' file (the root of the code tree)
* # using Clipper.
* %.exe : %.prg
* $(CLPC) $< $(CLPFLAGS)
* $(LD) $(CLPLDFLAGS) $* $(XOBJS),$@,nul, $(CLPLIBS) $(XLIBS) ;
*
* you can compile a Clipper program tst.prg that uses this as follows:
*
* make tst.exe XOBJS=regxsrch.obj CLPLDFLAGS='/se:512 /noe /nod' XLIBS='gnulib_l llibca'
*
*
* Returns:
* ~~~~~~~~
* -4 on parameter error,
* -3 on memory allocation (_exmgrab) error,
* -2 on regex error (regex compilation failed),
* -1 on no match,
* or the index (base 0) of the match.
*
*
* History:
* ~~~~~~~~
* 18 Jan 92 RjR - Initial version.
* 19 Jan 92 RjR - Bug fixes and cleanup of the Clipper interface.
* 20 Jan 92 RjR - Do the _exmgrab() only once, for speed and to avoid
* possible memory fragmentation. This gets us a 10%
* speed gain.
* - Buffer the regex from the last call, and do not
* recompile it if the current regex is the same.
* This gets us a further 35% speed gain.
* - Arrange things so that there is only one exit point.
* - Clean up in-code documentation.
* - Added debugging code. Define DEBUG to use it.
* 21 Jan 92 RjR - Cleanup and inspection.
*
*
* Author:
* ~~~~~~~
* Richard Reiner <rreiner@nexus.yorku.ca>
*
*
* Distribution:
* ~~~~~~~~~~~~~
* Copyright (C) 1992, Richard Reiner
*
* regxsrch.c comes with ABSOLUTELY NO WARRANTY. This is free software,
* and you are welcome to distribute it under the terms of the GNU General
* Public License, which covers both the warranty information and the
* terms for redistribution.
*
* See the file COPYING in the GNULIB distribution for details.
*
*/
#ifdef DEBUG
# define DEBUG_MSG(m) printf(m)
#else
# define DEBUG_MSG(m)
#endif
#include <regex.h>
#include <math.h>
#include <clipper.h>
#include <stdlib.h>
#include <string.h>
#ifdef DEBUG
# include <stdio.h>
#endif
#define PATBUFSIZ 2048
#define FMAPSIZ 256
#define LASTREGEXBUFSIZ 256
CLIPPER regex_srch (void) {
static struct re_pattern_buffer *rbuf;
static char *fmap, *lastregex;
static int callcount = 0, retval = -2;
register int parlen;
/* if the Clipper parameters are of the right number and type */
if (PCOUNT == 2 && ISCHAR(1) && ISCHAR(2)) {
/*
* Allocate memory the first time we are called. We do not
* allocate and free (_exmgrab() and _exmback()) each time we are
* called, since the time required for allocation and freeing is
* quite high relative to the time required for the actual regex
* match. Instead we alloc once, and never free until Clipper
* does it for us at the Clipper program's termination.
*/
if (callcount == 0) {
callcount++;
/* allocate memory from Clipper */
fmap = _exmgrab(FMAPSIZ);
rbuf = (struct re_pattern_buffer *) _exmgrab(sizeof (struct re_pattern_buffer));
rbuf->buffer = _exmgrab(PATBUFSIZ);
lastregex = _exmgrab(LASTREGEXBUFSIZ);
/* ensure lastregex is null terminated */
lastregex[LASTREGEXBUFSIZ - 1] = '\0';
}
/* if one of the _exmgrab()s failed */
if (fmap==NULL || rbuf==NULL || rbuf->buffer==NULL || lastregex==NULL) {
/* store allocation error indication for Clipper */
retval = -3;
} else { /* _exmgrab()s were OK */
/* initialize rbuf fields */
rbuf->allocated = PATBUFSIZ;
rbuf->translate = 0;
/* store length of target string for later repeated use */
parlen = _parclen(1, 1);
/* if this regex is not the same as the last one */
if (strncmp(lastregex, _parc(2,1), LASTREGEXBUFSIZ - 1) != 0) {
#ifdef DEBUG
DEBUG_MSG("Regex not the same as previous.\n");
#endif
/* store the regex for next time */
strncpy(lastregex, _parc(2,1), LASTREGEXBUFSIZ - 1);
/* compile the regex */
if (re_compile_pattern(_parc(2,1), _parclen(2,1), rbuf) != 0) {
/* store compilation error indication for Clipper */
retval = -2;
} else { /* the compilation was successful, so we search */
rbuf->fastmap = fmap;
retval = re_search(rbuf, _parc(1,1), parlen, 0, parlen-1, 0);
}
} else { /* regex is the same as the last one, so no need to recompile */
DEBUG_MSG("Regex same as previous.\n");
/* Search only if the last search, which was using this
same regex, did not produce an error. Otherwise, don't
change anything */
if (retval >= -1) {
retval = re_search(rbuf, _parc(1,1), parlen, 0, parlen-1, 0);
} else {
DEBUG_MSG("Last attempt produced error; not searching.\n");
}
}
}
} else { /* Clipper parameters were not OK */
/* store parameter error indication for Clipper */
retval = -4;
}
#ifdef DEBUG
printf("retval == %d.\n",retval);
#endif
_retni(retval);
return;
}